package net.lab1024.sa.admin.module.business.flow.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.config.CustomProcessDiagramGenerator;
import net.lab1024.sa.admin.module.business.flow.domain.form.FlwDeployInstanceAddForm;
import net.lab1024.sa.admin.module.business.flow.domain.form.FlwTaskQueryForm;
import net.lab1024.sa.admin.module.business.flow.domain.vo.FlwDeModelVO;
import net.lab1024.sa.admin.module.business.flow.domain.vo.FlwTaskVo;
import net.lab1024.sa.admin.module.business.flow.service.FlowServiceFactory;
import net.lab1024.sa.admin.module.business.flow.service.FlwInstanceService;
import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity;
import net.lab1024.sa.admin.module.system.employee.service.EmployeeService;
import net.lab1024.sa.admin.module.system.role.service.RoleService;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.domain.ResponseDTO;
import net.lab1024.sa.base.common.util.SmartPageUtil;
import net.lab1024.sa.base.common.util.SmartRequestUtil;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricActivityInstanceQuery;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.image.ProcessDiagramGenerator;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

@Slf4j
@Service
public class FlwInstanceServiceImpl extends FlowServiceFactory implements FlwInstanceService {

    @Resource
    private RoleService roleService;

    @Resource
    private EmployeeService employeeService;

    @Override
    public void startProcess(Map<String, Object> params) {
        // 1、获取流程id
        String processId = (String) params.get("processId");
        // 2、启动流程
        HashMap<String, Object> hashMap = new HashMap<>();
        // 3、结合传递过来的数据
        Set<String> keySet = params.keySet();
        for (String key : keySet) {
            if (key.equals("processId") ){
                continue;
            }
            String value =(String) params.get(key);
            if (key.contains(",")){
                String[] split = key.split(",");
                int i = 0;
               for (String s : split){
                   if (value.contains( ",")){
                       String[] split1 = value.split(",");
                       if (i <= split1.length){
                           hashMap.put(s,split1[i]);
                       }else {
                           hashMap.put(s,split1[0]);
                       }
                   }else {
                       hashMap.put(s,value);
                   }
                   i++;
               }
            }else {
                hashMap.put(key,value);
            }
        }

        // 记录流程的发起人
        Long requestUserId = SmartRequestUtil.getRequestUserId();
        identityService.setAuthenticatedUserId(requestUserId.toString());
        // 启动流程
        runtimeService.startProcessInstanceById(processId,hashMap);
    }

    @Override
    public PageResult<FlwTaskVo>  queryMyTask(FlwTaskQueryForm queryForm) {
        // 1、获取当前登录的用户
        Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
        Long requestUserId = SmartRequestUtil.getRequestUserId();
        log.info("FlwInstanceServiceImpl.queryMyTask：{}",requestUserId);
        // 2、task 查询
        TaskQuery taskQuery = taskService.createTaskQuery().active()
                .or() //默认or分支
                    .taskAssignee(requestUserId.toString())  // 查询审批人
                    .taskCandidateOrAssigned(requestUserId.toString())
                    .taskCandidateGroup(requestUserId.toString())
                .endOr()
                .orderByTaskCreateTime().desc();
        // 4、分页查询条件
        List<Task> taskList = taskQuery.listPage((int) ((page.getCurrent() - 1) * page.getSize()), (int) page.getSize());
        // 5、返回结果
        ArrayList<FlwTaskVo> flwTaskVoArrayList = new ArrayList<>();
        if (taskList != null){
            for (Task task : taskList) {
                FlwTaskVo flwTaskVo = new FlwTaskVo();
                flwTaskVo.setTaskId(task.getId());
                flwTaskVo.setCategory(task.getCategory());
                flwTaskVo.setAssigneeId(task.getAssignee());
                flwTaskVo.setProcDefId(task.getProcessDefinitionId());
                flwTaskVo.setTaskName(task.getName());
                flwTaskVo.setTaskDefKey(task.getTaskDefinitionKey());
                flwTaskVo.setHisProcInsId(task.getProcessInstanceId());
                flwTaskVo.setProcInsId(task.getProcessInstanceId());
                // 如果当前用户是流程的审批人，则设置审批人名称（前端用户如果含有审批人名称那就证明是审批人可以进行审批）
                if (flwTaskVo.getAssigneeId() != null){
                    EmployeeEntity employee = employeeService.getById(Long.valueOf(flwTaskVo.getAssigneeId()));
                    flwTaskVo.setAssigneeName(employee.getActualName());
                }
                // 查询出对应的流程定义的信息
                ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                        .processDefinitionId(flwTaskVo.getProcDefId()).singleResult();
                flwTaskVo.setProcDefName(processDefinition.getName());
                flwTaskVo.setProcDefKey(processDefinition.getKey());
                // 查出任务的发起人，并且设置
                if (flwTaskVo.getProcInsId() != null) { // 确保流程实例ID非空
                    try {
                        // 按流程实例ID查询历史流程实例（1个实例对应1条记录）
                        HistoricProcessInstance historicProcIns = historyService
                                .createHistoricProcessInstanceQuery()
                                .processInstanceId(flwTaskVo.getProcInsId())
                                .singleResult();
                        if (historicProcIns != null) {
                            // 获取发起人ID（startUserId 是创建流程时设置的 authenticatedUserId）
                            String startUserId = historicProcIns.getStartUserId();
                            flwTaskVo.setStartUserId(startUserId); // 给 VO 赋值发起人ID

                            // 可选：查询发起人姓名（关联员工表）
                            if (startUserId != null) {
                                EmployeeEntity startUser = employeeService.getById(Long.valueOf(startUserId));
                                if (startUser != null) {
                                    flwTaskVo.setStartUserName(startUser.getActualName()); // 发起人姓名
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.error("查询流程发起人失败，processInstanceId：{}", flwTaskVo.getProcInsId(), e);
                    }
                }
                // 通过BpmnModel对象来检查当前结点的定义信息
                flwTaskVo.setStatus(getUserTaskStatus(task.getProcessDefinitionId(),task.getTaskDefinitionKey()));
                flwTaskVoArrayList.add(flwTaskVo);
            }
        }

        return SmartPageUtil.convert2PageResult(page, flwTaskVoArrayList);
    }

    @Override
    public void completeTask(String id) {
        taskService.complete(id);
    }

    /**
     * 任务归还
     * @param id
     */
    @Override
    public void claimTask(String id) {
        taskService.claim(id, SmartRequestUtil.getRequestUserId().toString());
    }

    @Override
    public void unclaimTask(String id) {

    }

    @Override
    public byte[] diagram(String processId) {
        String processDefinitionId;
        // 获取当前的流程实例
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
        // 如果流程已经结束，则得到结束节点
        if (Objects.isNull(processInstance)) {
            HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery()
                    .processInstanceId(processId).singleResult();

            processDefinitionId = pi.getProcessDefinitionId();
        } else {
            // 如果流程没有结束，则取当前活动节点
            // 根据流程实例ID获得当前处于活动状态的ActivityId合集
            ProcessInstance pi = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(processId).singleResult();
            processDefinitionId = pi.getProcessDefinitionId();
        }

        // 获得活动的节点
        List<HistoricActivityInstance> highLightedFlowList = historyService
                .createHistoricActivityInstanceQuery()
                .processInstanceId(processId)
                .orderByHistoricActivityInstanceStartTime().asc().list();

        List<String> highLightedFlows = new ArrayList<>();
        List<String> highLightedNodes = new ArrayList<>();
        //高亮线
        for (HistoricActivityInstance tempActivity : highLightedFlowList) {
            if ("sequenceFlow".equals(tempActivity.getActivityType())) {
                //高亮线
                highLightedFlows.add(tempActivity.getActivityId());
            } else {
                //高亮节点
                highLightedNodes.add(tempActivity.getActivityId());
            }
        }
        //获取流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        ProcessEngineConfiguration configuration = processEngine.getProcessEngineConfiguration();
        //获取自定义图片生成器
        ProcessDiagramGenerator diagramGenerator = new CustomProcessDiagramGenerator();
        InputStream in = diagramGenerator
                .generateDiagram(bpmnModel, "png", highLightedNodes, highLightedFlows, configuration.getActivityFontName(),
                        configuration.getLabelFontName(), configuration.getAnnotationFontName(), configuration.getClassLoader(), 1.0, true);
        try {
            byte[] b = new byte[in.available()];
            in.read(b);
            return b;
        }catch (IOException e){

        }
        return null;
    }

    private Integer getUserTaskStatus(String processDefId,String taskDefKey){
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefId);
        Process mainProcess = bpmnModel.getMainProcess();
        Integer status = 0;
        log.info("FlwInstanceServiceImpl.getUserTaskStatus：{}", mainProcess);
        Collection<FlowElement> flowElements = mainProcess.getFlowElements();
        if (flowElements != null && flowElements.size() > 0){
            for (FlowElement flowElement : flowElements) {
                    if (flowElement instanceof UserTask){
                        UserTask userTask = (UserTask) flowElement;
                        if (userTask.getId().equals(taskDefKey)){
                            String assignee = userTask.getAssignee();
                            if (StringUtils.isNoneBlank(assignee)){
                                //  说明是审批人
                                    status =0;
                            }else{
                                status =1;
                            }
                        }
                    }
            }
        }
        log.info("FlwInstanceServiceImpl.getUserTaskStatus：{}", status);
        return status;
    }
}
